package menulogic

import (
	"context"

	"go-zero-admin/apps/system/cmd/rpc/internal/svc"
	"go-zero-admin/apps/system/cmd/rpc/syspb"
	"go-zero-admin/apps/system/model"
	"go-zero-admin/pkg/tool"
	"go-zero-admin/pkg/xerr"

	"github.com/duke-git/lancet/v2/convertor"
	"github.com/pkg/errors"
	"github.com/zeromicro/go-zero/core/logx"
)

type DelMenuLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
	getMenuListLogic *GetMenuListLogic
	getMenuRoleIds   *GetMenuRoleIdsLogic
}

func NewDelMenuLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DelMenuLogic {
	return &DelMenuLogic{
		ctx:              ctx,
		svcCtx:           svcCtx,
		Logger:           logx.WithContext(ctx),
		getMenuListLogic: NewGetMenuListLogic(ctx, svcCtx),
		getMenuRoleIds:   NewGetMenuRoleIdsLogic(ctx, svcCtx),
	}
}

func (l *DelMenuLogic) DelMenu(in *syspb.DelMenuReq) (*syspb.DelMenuResp, error) {
	if in.GetId() == 0 || (!in.GetIsDel() && in.GetUpdateUser() == "") {
		return nil, errors.Wrapf(xerr.NewErrMsg("删除菜单失败：参数缺失"),
			tool.GetErrMsgFormat("delete menu"), "params is not existed", in)
	}

	// 查询出所有菜单
	listResp, err := l.getMenuListLogic.GetMenuList(&syspb.GetMenuListReq{})
	if err != nil {
		return nil, err
	}
	list := listResp.GetList()
	if len(list) == 0 {
		return nil, errors.Wrapf(xerr.NewErrMsg("删除菜单失败：菜单数据不存在，不允许删除"),
			tool.GetErrMsgFormat("delete menu"), "menu list is not existed", in)
	}

	// 参数判断
	roleIdsResp, err := l.getMenuRoleIds.GetMenuRoleIds(&syspb.GetMenuRoleIdsReq{Id: in.GetId()})
	if err != nil || len(roleIdsResp.GetRoleIds()) > 0 {
		return nil, errors.Wrapf(xerr.NewErrMsg("删除菜单失败：菜单ID："+convertor.ToString(in.GetId())+" 已分配，不允许删除"),
			tool.GetErrMsgFormat("delete menu"), "menu is distributed", in)
	}

	// 子数据判断
	menus := l.findSonByPid(in.GetId(), list)
	if len(menus) > 0 {
		return nil, errors.Wrapf(xerr.NewErrMsg("删除菜单失败：菜单ID："+convertor.ToString(in.GetId())+" 存在子菜单，不允许删除"),
			tool.GetErrMsgFormat("delete menu"), "menu children is existed", in)
	}

	// 删除
	err = l.svcCtx.SysMenuModel.DeleteEx(l.ctx, nil, []int64{in.GetId()}, in.GetIsDel(), in.GetUpdateUser())
	if err != nil {
		return nil, errors.Wrapf(xerr.NewErrFindOneCode(err, model.ErrNotFound),
			tool.GetErrMsgFormat("delete menu"), err, in)
	}

	return &syspb.DelMenuResp{}, nil
}

// 查询出子数据
func (l *DelMenuLogic) findSonByPid(pid int64, list []*syspb.SysMenu) []*syspb.SysMenu {
	var children []*syspb.SysMenu
	for _, v := range list {
		if v.Pid != pid {
			continue
		}

		children = append(children, v)

		child := l.findSonByPid(v.Id, list)
		if len(child) == 0 {
			continue
		}

		children = append(children, child...)
	}
	return children
}
